#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import re
import os
import argparse
import seafileapi
import lzma
import logging
log = logging.getLogger(__name__)


class SeaFileIo:
    def __init__(self, server, username, password, repo_name="私人资料库"):
        self.client = seafileapi.connect(server, username, password)
        repos = self.client.repos.list_repos()
        find_repo = False
        for repo in repos:
            if repo.name == repo_name:
                find_repo = True
                self.repo = repo
                break
        if not find_repo:
            self.repo = self.client.repos.create_repo(repo_name, "")

    def is_exist_dir(self, path):
        '''
        Determine whether the path exists
        :param path:
        :return:
        '''
        exist = False
        try:
            dir = self.repo.get_dir(path)
            if dir:
                exist = True
        except seafileapi.exceptions.DoesNotExist:
            pass

        return exist

    def mkdir_parent(self, parentpath):
        rootdir = self.repo.get_dir('/')
        if parentpath[0] == '/':
            parentpath = parentpath[1:]

        parentdir = rootdir
        paths = parentpath.split('/')
        cur_path = "/"
        for subpath in paths:
            cur_path = cur_path + subpath + "/"
            if self.is_exist_dir(cur_path):
                parentdir = self.repo.get_dir(cur_path)
            else:
                parentdir = parentdir.mkdir(subpath)
        return parentdir

    def upload_file(self, parentpath, file_name, compress_file=True):
        rootdir = self.repo.get_dir('/')
        # assert len(rootdir.ls()) == 0

        if parentpath == '/':
            parentdir = rootdir
        elif self.is_exist_dir(parentpath):
            parentdir = self.repo.get_dir(parentpath)
        else:
            parentdir = rootdir.mkdir(parentpath[1:])

        fname = file_name.split('/')[-1]
        xz_fname = fname + ".xz"
        entries = parentdir.ls(force_refresh=True)
        for entry in entries:
            if (entry.name == fname) or (entry.name == xz_fname):
                entry.delete()

        if compress_file:
            lzc = lzma.LZMACompressor()
            with open(file_name, 'rb') as fp:
                in_datas = fp.read()
            xz_data1 = lzc.compress(in_datas)
            xz_data2 = lzc.flush()
            xz_data = b"".join([xz_data1, xz_data2])
            uploaded_file = parentdir.upload(xz_data, xz_fname)
        else:
            with open(file_name, 'rb') as fp:
                uploaded_file = parentdir.upload(fp, fname)
            fp.close()
            # parentdir.upload_local_file(file_name)

    def download_last_file(self, parentpath, file_head):
        '''
        '''
        download_file = self.repo.get_dir(parentpath)
        # get the file names in the dir
        file_list = (download_file.ls())
        log.info(file_list)
        # get the specify file
        file_head_list = []
        for seafile_class in file_list:
            if file_head in seafile_class.path:
                file_head_list.append(seafile_class.path)

        # sorted
        file_head_list.sort()

        download_file_path = self.repo.get_file(file_head_list[-1])
        log.info(download_file_path)
        file_name = download_file_path.path.split('/')[-1]
        with open(file_name, 'wb') as fp:
            fp.write(download_file_path.get_content())

    def download_dir(self, parentpath):
        '''
        download all files in path
        '''
        download_file = self.repo.get_dir(parentpath)
        # get the file names in the dir
        file_list = (download_file.ls())
        log.info(file_list)
        # get the specify file
        file_head_list = []
        for seafile_class in file_list:
            download_file_path = self.repo.get_file(seafile_class.path)
            log.info(download_file_path)
            file_name = download_file_path.path.split('/')[-1]
            with open(file_name, 'wb') as fp:
                fp.write(download_file_path.get_content())


class searchfile():
    def __init__(self):
        self.namelist = []

    def search(self, path='.', con='.*'):
        for filename in os.listdir(path):
            fp = os.path.join(path, filename)
            if os.path.isfile(fp) and re.match(con, os.path.basename(fp)):
                self.namelist.append(fp)
            elif os.path.isdir(fp):
                self.search(fp, con)
        return self.namelist


def main():
    parser = argparse.ArgumentParser(description="Upload files to seafile.")

    parser.add_argument('--upload', dest='upload_file',
                        help='Input upload files.(".*py .*txt")')
    parser.add_argument('--server', dest='server_url',
                        help='Input the server url.')
    parser.add_argument('--username', dest='user_name',
                        help='Input the username.')
    parser.add_argument('--password', dest='password',
                        help='Input the password.')
    parser.add_argument('--upload_dir', dest='upload_dir',
                        help='Input the upload dir.', default="")
    parser.add_argument('--repo', dest='repo_name',
                        help='Input the repo name.', default="私人资料库")

    args = parser.parse_args()

    seafile_client = SeaFileIo(
        args.server_url, args.user_name, args.password, args.repo_name)

    if args.upload_file != None:
        uploadpath = []
        for path in args.upload_file.split(" "):
            (p, f) = os.path.split(path)
            uploadpath = uploadpath + \
                (searchfile().search("./" + p,
                                     (f[0] == "*") and ("." + f) or f))
        if len(uploadpath) == 0:
            return
        uploadir = "/" + args.upload_dir
        seafile_client.mkdir_parent(uploadir)
        for fl in uploadpath:
            seafile_client.upload_file(uploadir, fl, compress_file=False)
    print("upload finish")

    # if args.upload_file == None:
    #    seafile_client.download_last_file('/' + args.download_dir.split('/',1)[-1], args.download_file)
    # else:
    #    seafile_client.upload_file('/' + args.upload_dir.split('/',1)[-1], args.upload_file, compress_file=False)


if __name__ == '__main__':
    log = logging.getLogger("")
    formatter = logging.Formatter(
        "%(asctime)s %(levelname)s " + "[%(module)s:%(lineno)d] %(message)s")
    # setup console logging
    log.setLevel(logging.INFO)
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)

    ch.setFormatter(formatter)
    log.addHandler(ch)

    main()
